package cloud.maque.sso.server.GrantTypeHandler;

import cloud.maque.auth.exceptions.UserInfoException;
import cloud.maque.auth.fegin.AuthUserFeginClient;
import cloud.maque.auth.model.BaseUserModel;
import cloud.maque.auth.model.LoginResponse;
import cloud.maque.common.core.exceptions.BusinessException;
import cloud.maque.common.core.exceptions.FlushException;
import cloud.maque.common.core.response.R;
import cloud.maque.common.totp.TotpUtils;
import cloud.maque.conf.MaqueProperties;
import cloud.maque.sso.server.service.UserHandle;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.data.model.AccessTokenModel;
import cn.dev33.satoken.oauth2.data.model.request.RequestAuthModel;
import cn.dev33.satoken.oauth2.granttype.handler.SaOAuth2GrantTypeHandlerInterface;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.core.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * TOTP登录验证(如：谷歌认证器，微软认证器等基于时间算法的验证码
 */
@Component
public class TotpGrantTypeHandler implements SaOAuth2GrantTypeHandlerInterface {


    @Autowired
    UserHandle userHandle;

    @Autowired
    MaqueProperties maqueProperties;

    @Override
    public String getHandlerGrantType() {
        return "totp";
    }

    @Override
    public AccessTokenModel getAccessToken(SaRequest req, String clientId, List<String> scopes) {

        // 获取前端提交的参数
        String totpCode = req.getParam("code");
        String username = req.getParamNotNull("username");
        String password = req.getParamNotNull("password");
        String bind = req.getParam("bind");

        if (StrUtil.isEmptyIfStr(bind) || !"1".equals(bind)) {
            totpCode = req.getParamNotNull("code");
        }

        SaResult saResult = userHandle.checkPass(username, password);
        if (saResult.getCode() != 200) {
            throw new UserInfoException("错误：" + saResult.getMsg());
        }

        LoginResponse loginResponse = (LoginResponse) saResult.getData();

        String totpSecret = userHandle.getUserTotpSecret(loginResponse.getUserId());

        if (!StrUtil.isEmptyIfStr(bind) && "1".equals(bind)) {
            if (StrUtil.isEmptyIfStr(totpSecret)) {
                String totpSecretTmp = TotpUtils.createTotpSecret();
                String qrUrl = TotpUtils.createQrSecretUrl(username, totpSecretTmp);
                userHandle.updateUserTotpSecret(loginResponse.getUserId(), totpSecretTmp);
                //把二维码返回给前端
                throw new FlushException(201, qrUrl);
            } else {
                throw new BusinessException("时间密钥已设置，不能再次绑定,如果忘记密码，请到联系管理员");
            }
        } else {
            //如果为空，则返回密钥的二维码
            if (StrUtil.isEmptyIfStr(totpSecret)) {
                throw new BusinessException("时间密钥未设置,请先绑定密钥");
            }
        }


        Boolean isValidCode = TotpUtils.VerifyTotp(totpSecret, totpCode);
        if (!isValidCode) {
            throw new UserInfoException("验证码不正确");
        }

        // 4、构建 ra 对象
        RequestAuthModel ra = new RequestAuthModel();
        ra.clientId = clientId;
        ra.loginId = loginResponse.getUserId();
        ra.scopes = scopes;

        // 5、生成 Access-Token
        AccessTokenModel at = SaOAuth2Manager.getDataGenerate().generateAccessToken(ra, true);
        return at;
    }
}
